<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue'

// 游戏配置
const GRID_SIZE = 20
const BASE_SPEED = 150
const GAME_SPEED = ref(BASE_SPEED)

// 游戏状态
const gameRunning = ref(false)
const score = ref(0)
const level = ref(1)
const gameOver = ref(false)
const gameTime = ref(0)
let timeInterval: number

// 蛇的数据
const snake = ref([
  { x: 10, y: 10 }, // 蛇头
])
const direction = ref('right')
const food = ref({ x: 5, y: 5 })

// 生成随机食物位置
const generateFood = () => {
  const x = Math.floor(Math.random() * GRID_SIZE)
  const y = Math.floor(Math.random() * GRID_SIZE)
  food.value = { x, y }
}

// 检查碰撞
const checkCollision = (head: { x: number; y: number }) => {
  // 检查墙壁碰撞
  if (
    head.x < 0 ||
    head.x >= GRID_SIZE ||
    head.y < 0 ||
    head.y >= GRID_SIZE
  ) {
    return true
  }

  // 检查自身碰撞
  return snake.value.slice(1).some(segment => 
    segment.x === head.x && segment.y === head.y
  )
}

// 更新游戏时间
const updateGameTime = () => {
  if (gameRunning.value && !gameOver.value) {
    gameTime.value++
  }
}

// 游戏循环
let gameInterval: number

// 移动蛇
const moveSnake = () => {
  if (!gameRunning.value || gameOver.value) return

  const head = { ...snake.value[0] }

  switch (direction.value) {
    case 'up':
      head.y--
      break
    case 'down':
      head.y++
      break
    case 'left':
      head.x--
      break
    case 'right':
      head.x++
      break
  }

  if (checkCollision(head)) {
    gameOver.value = true
    clearInterval(gameInterval)
    clearInterval(timeInterval)
    return
  }

  snake.value.unshift(head)

  // 检查是否吃到食物
  if (head.x === food.value.x && head.y === food.value.y) {
    score.value++
    if (score.value % 5 === 0) {
      level.value++
      GAME_SPEED.value = Math.max(50, BASE_SPEED - (level.value - 1) * 20)
      if (gameInterval) {
        clearInterval(gameInterval)
        gameInterval = setInterval(moveSnake, GAME_SPEED.value)
      }
    }
    generateFood()
  } else {
    snake.value.pop()
  }
}

// 键盘控制
const handleKeydown = (e: KeyboardEvent) => {
  switch (e.key) {
    case 'ArrowUp':
      if (direction.value !== 'down') direction.value = 'up'
      break
    case 'ArrowDown':
      if (direction.value !== 'up') direction.value = 'down'
      break
    case 'ArrowLeft':
      if (direction.value !== 'right') direction.value = 'left'
      break
    case 'ArrowRight':
      if (direction.value !== 'left') direction.value = 'right'
      break
    case ' ':
      toggleGame()
      break
  }
}

// 格式化时间
const formatTime = (seconds: number) => {
  const mins = Math.floor(seconds / 60)
  const secs = seconds % 60
  return `${mins.toString().padStart(2, '0')}:${secs.toString().padStart(2, '0')}`
}

// 开始游戏
const startGame = () => {
  gameRunning.value = true
  gameOver.value = false
  score.value = 0
  level.value = 1
  gameTime.value = 0
  GAME_SPEED.value = BASE_SPEED
  snake.value = [{ x: 10, y: 10 }]
  direction.value = 'right'
  generateFood()
  timeInterval = setInterval(updateGameTime, 1000)
}

onMounted(() => {
  window.addEventListener('keydown', handleKeydown)
})

onUnmounted(() => {
  window.removeEventListener('keydown', handleKeydown)
  clearInterval(gameInterval)
  clearInterval(timeInterval)
})

// 监听游戏状态
const toggleGame = () => {
  if (gameOver.value) {
    startGame()
  } else {
    gameRunning.value = !gameRunning.value
    if (gameRunning.value) {
      gameInterval = setInterval(moveSnake, GAME_SPEED.value)
      timeInterval = setInterval(updateGameTime, 1000)
    } else {
      clearInterval(gameInterval)
      clearInterval(timeInterval)
    }
  }
}
</script>

<template>
  <div class="snake-game">
    <div class="game-header">
      <h2>贪吃蛇游戏</h2>
      <div class="game-info">
        <div class="info-item">
          <span class="label">得分:</span>
          <span class="value">{{ score }}</span>
        </div>
        <div class="info-item">
          <span class="label">关卡:</span>
          <span class="value">{{ level }}</span>
        </div>
        <div class="info-item">
          <span class="label">时间:</span>
          <span class="value">{{ formatTime(gameTime) }}</span>
        </div>
      </div>
    </div>
    
    <div class="game-grid">
      <div
        v-for="y in GRID_SIZE"
        :key="y"
        class="grid-row"
      >
        <div
          v-for="x in GRID_SIZE"
          :key="x"
          class="grid-cell"
          :class="{
            'snake': snake.some(s => s.x === x - 1 && s.y === y - 1),
            'food': food.x === x - 1 && food.y === y - 1
          }"
        ></div>
      </div>
    </div>

    <div class="game-controls">
      <el-button
        type="primary"
        @click="toggleGame"
        :class="{ 'pulse': !gameRunning && !gameOver }"
      >
        {{ gameOver ? '重新开始' : (gameRunning ? '暂停' : '开始') }}
      </el-button>
      <div class="controls-tip">
        <p>使用方向键控制方向</p>
        <p>空格键暂停/开始</p>
      </div>
    </div>

    <el-dialog
      v-model="gameOver"
      title="游戏结束"
      width="300px"
      :close-on-click-modal="false"
      :show-close="false"
      center
    >
      <div class="game-over-content">
        <div class="final-stats">
          <p>最终得分: <span>{{ score }}</span></p>
          <p>达到关卡: <span>{{ level }}</span></p>
          <p>游戏时长: <span>{{ formatTime(gameTime) }}</span></p>
        </div>
        <el-button type="primary" @click="startGame" class="restart-btn">重新开始</el-button>
      </div>
    </el-dialog>
  </div>
</template>

<style scoped>
.snake-game {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 20px;
  background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
  border-radius: 12px;
  box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
}

.game-header {
  text-align: center;
  margin-bottom: 20px;
}

.game-header h2 {
  color: #2c3e50;
  font-size: 1.5em;
  margin-bottom: 15px;
  text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.1);
}

.game-info {
  display: flex;
  gap: 15px;
  justify-content: center;
  background: rgba(255, 255, 255, 0.9);
  padding: 8px 15px;
  border-radius: 6px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.info-item {
  display: flex;
  align-items: center;
  gap: 8px;
}

.info-item .label {
  color: #666;
  font-size: 0.9em;
}

.info-item .value {
  color: #409EFF;
  font-size: 1.2em;
  font-weight: bold;
}

.game-grid {
  display: grid;
  grid-template-rows: repeat(20, 15px);
  gap: 1px;
  background-color: rgba(0, 0, 0, 0.1);
  padding: 8px;
  border-radius: 8px;
  box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.1);
}

.grid-row {
  display: grid;
  grid-template-columns: repeat(20, 15px);
  gap: 1px;
}

.grid-cell {
  width: 15px;
  height: 15px;
  background-color: rgba(255, 255, 255, 0.9);
  border-radius: 2px;
  transition: all 0.1s ease;
}

.snake {
  background-color: #409EFF;
  border-radius: 4px;
  box-shadow: 0 0 4px rgba(64, 158, 255, 0.6);
  transform: scale(0.95);
}

.food {
  background-color: #67C23A;
  border-radius: 50%;
  box-shadow: 0 0 8px rgba(103, 194, 58, 0.6);
  animation: pulse 1s infinite;
}

.game-controls {
  margin-top: 20px;
  text-align: center;
}

.controls-tip {
  margin-top: 10px;
  color: #666;
  font-size: 0.9em;
}

.controls-tip p {
  margin: 5px 0;
}

.game-over-content {
  text-align: center;
}

.final-stats {
  margin-bottom: 20px;
}

.final-stats p {
  margin: 10px 0;
  font-size: 1.1em;
}

.final-stats span {
  color: #409EFF;
  font-weight: bold;
}

.restart-btn {
  width: 100%;
  margin-top: 10px;
}

@keyframes pulse {
  0% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.1);
  }
  100% {
    transform: scale(1);
  }
}

.pulse {
  animation: button-pulse 2s infinite;
}

@keyframes button-pulse {
  0% {
    transform: scale(1);
    box-shadow: 0 0 0 0 rgba(64, 158, 255, 0.4);
  }
  70% {
    transform: scale(1.05);
    box-shadow: 0 0 0 10px rgba(64, 158, 255, 0);
  }
  100% {
    transform: scale(1);
    box-shadow: 0 0 0 0 rgba(64, 158, 255, 0);
  }
}
</style>